package com.lee.account.aspect;


import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.lee.account.entity.AccountLog;
import com.lee.account.jwt.Token;
import com.lee.account.service.AccountLogService;
import com.lee.account.utils.StringUtil;

/**
 * 日志切面
 * @author liyou
 * @date 2019年9月3日 下午3:59:31
 */
@Aspect
@Component
public class LogAspect {

	public static final Logger logger = LoggerFactory.getLogger(LogAspect.class);
	
	@Autowired
	private AccountLogService accountLogService;
    /**
     * 切入点描述 这个是controller包的切入点
     */
	@Pointcut("execution(* com.lee.account.controller.*.*(..))")
    public void operationLog(){}


    /**
     * 环绕增强，相当于MethodInterceptor
     */
    @Around("operationLog()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Object res = null;
        long time = System.currentTimeMillis();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = attributes.getRequest();
        try {
            res =  joinPoint.proceed();
            time = System.currentTimeMillis() - time;
            return res;
        } finally {
            try {
                //方法执行完成后增加日志
                addOperationLog(joinPoint,res,time,request);
            }catch (Exception e){
                logger.error("LogAspect 操作失败：" + e.getMessage(),e);
            }
        }
    }

    private void addOperationLog(JoinPoint joinPoint, Object res, long time ,HttpServletRequest request){
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        AccountLog accountLog = new AccountLog();
        accountLog.setRunTime(time);
        accountLog.setReturnValue(JSON.toJSONString(res));
        accountLog.setId(StringUtil.getUUID());
        accountLog.setArgs(JSON.toJSONString(joinPoint.getArgs()));
        accountLog.setMethod(signature.getDeclaringTypeName() + "." + signature.getName());
        accountLog.setUrl(request.getRequestURI());
        accountLog.setUserId(Token.getUsernameByToken(request.getHeader("access_token")));
        
        //TODO 这里保存日志
        accountLogService.insert(accountLog);
    }


    @Before("operationLog()")
    public void doBeforeAdvice(JoinPoint joinPoint){
    	logger.info("进入方法前执行.....");

    }

    /**
     * 处理完请求，返回内容
     * @param ret
     */
    @AfterReturning(returning = "ret", pointcut = "operationLog()")
    public void doAfterReturning(Object ret) {
        logger.info("方法的返回值 : " + ret);
    }

    /**
     * 后置异常通知
     */
    @AfterThrowing("operationLog()")
    public void throwss(JoinPoint jp){
        logger.info("方法异常时执行.....");
    }


    /**
     * 后置最终通知,final增强，不管是抛出异常或者正常退出都会执行
     */
    @After("operationLog()")
    public void after(JoinPoint jp){
        logger.info("方法最后执行.....");
    }

}
